#include <nvs_flash.h>
#include <esp_event.h>
#include <esp_wifi.h>
#include <esp_log.h>
#include <esp_netif.h>
#include <esp_netif_ip_addr.h>
#include <string.h>
#include <stdlib.h>
#include "user.h"
#include "BSP_WiFi.h"
#include "esp_smartconfig.h"
#include "IO_KEY_LED.h"

EventGroupHandle_t WiFi_EventGroupHandle = NULL;


#define WIFI_HAND_MOV       //手动配置
#define WIFI_APP            //APP配置

void init_nvs() {
	/*尝试初始化一次nvs_flash*/
    esp_err_t err = nvs_flash_init();
    if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND){
    /*第一次初始化失败, 检查错误, 处理错误, 重新初始化*/
        nvs_flash_erase();
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK(err);
}

#ifdef WIFI_HAND_MOV
void wifi_Manual_event_handler(void *arg, esp_event_base_t eventBase, int32_t eventID, void *eventData){
    ip_event_got_ip_t *ip = eventData;
    if(eventBase == WIFI_EVENT){
        switch (eventID) {
            default:    break;
            case WIFI_EVENT_STA_START:
                ESP_LOGI("BSP_Wifi", "WIFI_STARTED\n"); 
                esp_wifi_connect(); break;
            case WIFI_EVENT_STA_DISCONNECTED:
                ESP_LOGI("BSP_Wifi", "Connect failed\n"); 
                xEventGroupSetBits(Oled_EventGroupHandle,OLED_WIFI_Fail);
                esp_wifi_connect();	break;
            case WIFI_EVENT_STA_CONNECTED:
                ESP_LOGI("BSP_Wifi", "Connect Succes\n"); 
                //xEventGroupSetBits(Oled_EventGroupHandle,OLED_WIFI_SUCCEED);//加上事件setbit会任务卡死
                break;

        }
    }else if(eventBase == IP_EVENT){
        if(eventID == IP_EVENT_STA_GOT_IP){
            ESP_LOGI("BSP_Wifi","connected, got ip: "IPSTR"\n", IP2STR(&ip->ip_info.ip));
             xEventGroupSetBits(WiFi_EventGroupHandle,WIFI_CONNECT_SUCCESS);
            xEventGroupSetBits(Oled_EventGroupHandle,OLED_WIFI_SUCCEED);
        }
    }
}

void WiFi_Manual_Init(void)
{
    //WiFi_EventGroupHandle = xEventGroupCreate();

    init_nvs();

    esp_event_handler_instance_t wifi_handler,ip_handler;
    esp_event_loop_create_default();
    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
									    wifi_Manual_event_handler, NULL, &wifi_handler);
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
									    wifi_Manual_event_handler, NULL, &ip_handler);

    
    esp_netif_t *pEsp_wifi_netif;
    esp_netif_init();
    /*创建wifi sta模式的默认netif, 返回一个指针*/
    pEsp_wifi_netif = esp_netif_create_default_wifi_sta();

    /* (非必须) 这行代码是修改ESP32的主机名, 即WiFi设备名, 连接其他WiFi时显示的名称 */
    esp_netif_set_hostname(pEsp_wifi_netif, "ESP_wu_xc");// 不建议使用汉字

    wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&wifi_init_config);

    /* 第二步, WiFi配置 */
    wifi_config_t wifi_config = {
        .sta = {
        .ssid = "LC吸尘器110",       // wifi名（ssid）   LC吸尘器110         C栋427
        .password = "LC110110",// wifi密码           LC110110            88889671
        }
    };
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_set_mode(WIFI_MODE_STA);  // 设置工作模式

    /* 第三步, 启动WiFi */
    esp_wifi_start();

}
#endif

#ifdef WIFI_APP

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
static const int CONNECTED_BIT = WIFI_CONNECT_NO_FINISH;
static const int ESPTOUCH_DONE_BIT = WIFI_CONNECT_SUCCESS;
static const char *TAG = "smartconfig_example";

static void smartconfig_example_task(void * parm);

static void event_auto_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        xEventGroupClearBits(WiFi_EventGroupHandle, CONNECTED_BIT);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(WiFi_EventGroupHandle, CONNECTED_BIT);
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
        ESP_LOGI(TAG, "Scan done");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP_LOGI(TAG, "Found channel");
        xEventGroupSetBits(Oled_EventGroupHandle,OLED_WIFI_APP_CONNECT);    //app已经连上
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
        ESP_LOGI(TAG, "Got SSID and password");

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        wifi_config_t wifi_config;
        uint8_t ssid[33] = { 0 };
        uint8_t password[65] = { 0 };
        uint8_t rvd_data[33] = { 0 };

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if (wifi_config.sta.bssid_set == true) {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        ESP_LOGI(TAG, "SSID:%s", ssid);
        ESP_LOGI(TAG, "PASSWORD:%s", password);
        if (evt->type == SC_TYPE_ESPTOUCH_V2) {
            ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );
            ESP_LOGI(TAG, "RVD_DATA:");
            for (int i=0; i<33; i++) {
                printf("%02x ", rvd_data[i]);
            }
            printf("\n");
        }

        ESP_ERROR_CHECK( esp_wifi_disconnect() );
        ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
        esp_wifi_connect();
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
        xEventGroupSetBits(WiFi_EventGroupHandle,ESPTOUCH_DONE_BIT);
        
        
    }
}

void WiFi_auto_Init(void)
{
    init_nvs();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_auto_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_auto_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_auto_handler, NULL) );

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

static void smartconfig_example_task(void * parm)
{
    EventBits_t uxBits;
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
    while (1) {
        uxBits = xEventGroupWaitBits(WiFi_EventGroupHandle, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
        if(uxBits & CONNECTED_BIT) {
            ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if(uxBits & ESPTOUCH_DONE_BIT) {
            ESP_LOGI(TAG, "smartconfig over");
            esp_smartconfig_stop();
            xEventGroupSetBits(Oled_EventGroupHandle,OLED_WIFI_SUCCEED);        //wifi连接成功
            vTaskDelete(NULL);
       }
    }
}

#endif

//WiFi初始化事件组
void WiFi_Init_Task(void*p)
{
    static u8 Event_flag;
    while (1)
    {
        Event_flag = xEventGroupWaitBits(Key_EventGroupHandle , 
                                        KEY_RIGHT_EVENT|KEY_LEFT_EVENT, 
                                        pdTRUE,                     //清理事件 防止重复刷新 
                                        pdFALSE,                    //或语句
                                        portMAX_DELAY);
        //taskENTER_CRITICAL(1);                                  
        if (KEY_RIGHT_EVENT == (Event_flag&KEY_RIGHT_EVENT))
        {
            LED_OUT(LED_2,1);
            WiFi_auto_Init();
            vTaskDelete(WiFi_Init_Task_Handle);
        }
        if (KEY_LEFT_EVENT == (Event_flag&KEY_LEFT_EVENT))
        {
            LED_OUT(LED_1,1);
            WiFi_Manual_Init();
            vTaskDelete(WiFi_Init_Task_Handle);
        }
        //taskEXIT_CRITICAL(1);
    }
    
}
